iT邦幫忙

0

[Golang]同步工具-sync包的Pool(下)-心智圖總結

  • 分享至 

  • xImage
  •  

1. 池清理函數
Go語言運行時系統中的垃圾回收器,在每次開始執行之前,都會對所有已創建的臨時對象池中的值進行全面性的清除。
(sync包在被初始化的時候,會向Go語言運行時系統註冊一個函數,這個函數的功能就是清除,所有已創建的臨時對象池。)

2. 池滙總列表
在sync包中,有一個包級私有的全域變數。這個變數代表當前的程序中使用的所有臨時對象池滙總。可以稱為池滙總列表。在一個臨時對象池的Get方法和Put方法第一次被呼叫的時候,這個池就會被添加到池滙總列表中。
如此,池清理函數能訪問到所有正在被使用的臨時對象池。

3. 本地池、私有臨時對象、共享臨時對象列表的關係
在本地池列表中,每個本地池都包含三個字段,它們是儲存私有臨時對象的字段private、共享臨時對象列表的字段shared,以及一個sync.Mutex類型的嵌入字段。

4. 臨時對象池,是怎樣利用內部數據結構來存取值?
臨時對象池的Put方法,會先試圖把新的臨時對象,儲存到對應的本地池的private字段中,以便在後面要Get臨時對象的時候,可以拿到一個可以用的值。
只有當這個private字段已經存有某個值時,Put方法才會去訪問本地池的shared字段。

當Put方法,發現本地池的private字段已經有值,就會去訪問本地池的shared字段。
由於shared字段是共享的,所以此時必須受到互斥鎖的保護,才能把新的臨時對象追加到共享臨時對象的列表末尾。
(本地池嵌入的sync.Mutex類型的字段)

臨時對象池的Get方法,會先試圖從對應的本地池的private字段取得一個臨時對象。
只有當這個private字段的值為nil時,它才會去訪問本地池的shared字段。

當Get方法,發現本地池的private字段沒有值時,就會訪問shared字段。會在互斥鎖的保護下,取出共享臨時對象列表的最後一個元素。
如果Get方法,發現所有的臨時對象池,都是空的,就會呼叫臨時對象池的New字段的函數,如果這個字段的值是nil,那就回傳nil。

  1. 一個本地池的shared字段原則上可以被任何goroutine中的代碼訪問到,不論這個goroutine關聯是哪一個P
    而一個本地池的private字段,只能被goroutine所關聯的P訪問到。(P級私有)

https://ithelp.ithome.com.tw/upload/images/20201208/201317281et8HbnqcL.png

https://ithelp.ithome.com.tw/upload/images/20201208/20131728NEwNqWpez2.png

參考來源:
郝林-Go语言核心36讲
https://github.com/hyper0x/Golang_Puzzlers
https://golang.org/pkg/cmd/go/internal/test/


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言